package com.hsh.txt
{
	import com.hsh.graph.Pos;
	import com.hsh.graph.Visuel;
	import flash.display.Sprite;
	import flash.text.engine.TextBlock;
	import flash.text.engine.TextLine;
	import flash.text.TextFormat;
	import flash.utils.Dictionary;
	
	/**
	 * Champ de texte non multiligne
	 * @author Jean-Marie@home
	 */
	public class Champ
	{
		static public const PROP:Vector.<String> = new <String>["gauche","haut","largeur","hauteur"];
		protected var _visuel:Visuel;
		protected var _sprite:Sprite;
		protected var _ligne:TextLine;
		protected var _bloc:TextBlock;
		
		private var _val:Dictionary = new Dictionary();
		protected var _run:Run = new Run;
		protected var _mg:Marge = new Marge;
		
		/**
		 * Champ de texte 
		 * @param	v	visuel support
		 * @param	txt	texte à afficher
		 * @param	hAlign	alignement horizontal (anglais)
		 * @param	vAlign	alignement vertical (anglais)
		 */
		public function Champ(v:Visuel, txt:String, hAlign:Pos = null, vAlign:Pos = null)
		{
			_visuel = v;
			sur(Sprite(_visuel.diffuseur));
			cadrer(0, 0, 0, 0);
			emarger(3, 3, 3, 3, 0, 0, 0);
			aligner(hAlign || Pos.CENTRE, vAlign || Pos.MILIEU);
			texte = txt;
		}
		
		public function siModif(p:String, val:*, callback:Function):void
		{
			if (_val[p] != val)
			{
				_val[p] = val;
				callback();
			}
		}
		public function actualiser():void
		{
			tailler(_visuel.largeur, _visuel.hauteur);
			var largeurUtile:Number = largeur - _mg.horizontales;
			
			if (largeurUtile < 5)
				return;
			if (_ligne == null)
			{
				_bloc = new TextBlock(_run.element);
				_ligne = _bloc.createTextLine(null, largeurUtile);
			}
			else
			{
				_bloc.content = _run.element;
				
				if (_sprite.contains(_ligne))
					_sprite.removeChild(_ligne);
				_ligne = _bloc.recreateTextLine(_ligne, null, largeurUtile);
			}
			_run.element.eventMirror = _sprite;
			if (_ligne != null)
				_alignerTexte();
		}
		
		private function _alignerTexte():void
		{
			_sprite.addChild(_ligne);
			// _sprite.mouseChildren = false;
			switch (_mg.alignHor)
			{
				case Pos.GAUCHE: 
					_ligne.x = gauche + _mg.gauche;
					break;
				case Pos.CENTRE: 
					_ligne.x = gauche + ((largeur - _ligne.textWidth) / 2);
					break;
				case Pos.DROITE: 
					_ligne.x = gauche + (largeur - (_mg.droite + _ligne.textWidth));
					break;
				default: 
					_ligne.x = gauche;
			}
			switch (_mg.alignVer)
			{
				case Pos.HAUT: 
					_ligne.y = haut + _mg.haut + _ligne.ascent;
					break;
				case Pos.MILIEU: 
					_ligne.y = haut + ((hauteur + _ligne.ascent) / 2);
					break;
				case Pos.BAS: 
					_ligne.y = haut + (hauteur - (_ligne.descent + _mg.bas));
					break;
				default: 
					_ligne.y = haut;
			}
		}
		
		/**
		 * Définit l'alignement horizontal et vertical
		 * @param	hAli	alignement horizontal
		 * @param	vAli	alignement vertical
		 */
		public function aligner(hAli:Pos, vAli:Pos):void
		{
			_mg.aligner(hAli, vAli);
			actualiser();
		}
		
		/**
		 * Définit la position et la taille du visuel
		 * @param	x	gauche du visuel
		 * @param	y	haut du visuel
		 * @param	l	largeur du visuel
		 * @param	h	hauteur du visuel
		 */
		public function cadrer(x:Number, y:Number, l:Number, h:Number):void
		{
			placer(x, y);
			tailler(l, h);
		}
		
		/**
		 * a. Fermeture des écouteurs b. Suppression de la liste d'affichage
		 * c. Annulation des valeurs _etat, _largeur, _hauteur, ed.
		 */
		public function detruire():void
		{

			if (_ligne != null && _sprite.contains(_ligne))
				_sprite.removeChild(_ligne);
				
			for each (var pr:String in PROP) 
			{
				delete _val[pr];
			}

			_run.detruire();
			_mg.detruire();
			
			_val = null;
			_ligne = null;
			_bloc = null;
			_sprite = null;
		}
		
		/**
		 * Définition des marges
		 * @param	g	gauche
		 * @param	d	droite
		 * @param	h	haut
		 * @param	b	bas
		 * @param	indent	indentation de paragraphe
		 * @param	inlgn	espace entre les lignes
		 * @param	inspc	espace entre les caractères
		 */
		public function emarger(g:int, d:int, h:int, b:int, indent:Number, inlgn:Number, spc:Number):void
		{
			_mg.emarger(g, d, h, b, indent, inlgn, spc);
			actualiser();
		}
		
		/**
		 * Définition de la décoration du texte
		 * @param	g	gras
		 * @param	i	ital
		 * @param	s	souligne
		 * @param	b	barré
		 * @param	ex	exposant
		 * @param	id	indice
		 */
		public function decorer(g:Boolean = false, i:Boolean = false, s:Boolean = false, b:Boolean = false, ex:Boolean = false, id:Boolean = false):void
		{
			_run.decorer(g, i, s, b, ex, id);
			actualiser();
		}
		
		/**
		 * Définition du format du texte
		 * @param	p	police
		 * @param	t	taille
		 * @param	c	couleur
		 * @param	a	alpha
		 */
		public function formater(p:String, t:Number, c:uint, a:Number=1.0, g:Boolean = false, i:Boolean = false, s:Boolean = false, b:Boolean = false):void
		{
			_run.formater(p, t, c, a);
			decorer(g, i, s, b);
		}
		
		/**
		 * Définit la position
		 * @param	x	gauche du visuel
		 * @param	y	haut du visuel
		 */
		public function placer(x:Number, y:Number):void
		{
			gauche = x;
			haut = y;
		}
		
		/**
		 * Définir le parent
		 * @param	c	conteneur
		 */
		public function sur(s:Sprite, px:Number = NaN, py:Number = NaN):void
		{
			_sprite = s;
			if (!isNaN(py))
				placer(px, py);
		}
		
		/**
		 * Définit la taille du visuel
		 * @param	l	largeur du visuel
		 * @param	h	hauteur du visuel
		 */
		public function tailler(l:Number, h:Number):void
		{
			largeur = l;
			hauteur = h;
		}
		
		/**
		 * Position de la gauche sur le parent en pixels
		 */
		public function get gauche():Number
		{
			return _val["gauche"];
		}
		
		public function set gauche(value:Number):void
		{
			siModif("gauche", value, actualiser);
		}
		
		/**
		 * Position du haut sur le parent en pixels
		 */
		public function get haut():Number
		{
			return _val["haut"];
		}
		
		public function set haut(value:Number):void
		{
			siModif("haut", value, actualiser);
		}
		
		/**
		 * Hauteur en pixels du visuel
		 */
		public function get largeur():Number
		{
			return _val["largeur"];
		}
		
		public function set largeur(value:Number):void
		{
			siModif("largeur", value, actualiser);
		}
		
		/**
		 * Hauteur en pixels du visuel
		 */
		public function get hauteur():Number
		{
			return _val["hauteur"];
		}
		
		public function set hauteur(value:Number):void
		{
			siModif("hauteur", value, actualiser);
		}
		
		/**
		 * Nom de la police de caractère
		 */
		public function get police():String
		{
			return _run.police;
		}
		
		public function set police(value:String):void
		{
			_run.siModif("police", value, actualiser); 			
		}
		
		/**
		 * Taille de la police de caractère
		 */
		public function get taille():Number
		{
			return _run.taille;
		}
		
		public function set taille(value:Number):void
		{
			_run.siModif("taille", value, actualiser);
		}
		
		/**
		 * Couleur de la police de caractère
		 */
		public function get couleur():uint
		{
			return _run.couleur;
		}
		
		public function set couleur(value:uint):void
		{
			_run.siModif("couleur", value, actualiser);
		}
		
		/**
		 * Opacité du texte (0:transparent 1:opaque)
		 */
		public function get alpha():Number
		{
			return _run.alpha;
		}
		
		public function set alpha(value:Number):void
		{
			_run.siModif("alpha", value, actualiser);
		}
		
		/**
		 * Mettre le texte en gras ?
		 */
		public function get gras():Boolean
		{
			return _run.gras;
		}
		
		public function set gras(value:Boolean):void
		{
			_run.siModif("gras", value, actualiser);
		}
		
		/**
		 * Mettre le texte en italiques
		 */
		public function get ital():Boolean
		{
			return _run.ital;
		}
		
		public function set ital(value:Boolean):void
		{
			_run.siModif("ital", value, actualiser);
		}
		
		/**
		 * Marge de gauche
		 */
		public function get mgGauche():Number
		{
			return _mg.gauche;
		}
		
		public function set mgGauche(value:Number):void
		{
			_mg.siModif("gauche", value, actualiser);
		}
		
		/**
		 * Marge de droite
		 */
		public function get mgDroite():Number
		{
			return _mg.droite;
		}
		
		public function set mgDroite(value:Number):void
		{
			_mg.siModif("droite", value, actualiser);
		}
		
		/**
		 * Marge du haut
		 */
		public function get mgHaut():Number
		{
			return _mg.haut;
		}
		
		public function set mgHaut(value:Number):void
		{
			_mg.siModif("haut", value, actualiser);
		}
		
		/**
		 * Marge du bas
		 */
		
		public function get mgBas():Number
		{
			return _mg.bas;
		}
		
		public function set mgBas(value:Number):void
		{
			_mg.siModif("bas", value, actualiser);
		}
		
		/**
		 * Indentation de début de paragraphe
		 */
		public function get indentation():Number
		{
			return _mg.indentation;
		}
		
		public function set indentation(value:Number):void
		{
			_mg.siModif("indentation", value, actualiser);
		}
		
		/**
		 * Espace supplémentaire vertical entre les lignes
		 */
		
		public function get interligne():Number
		{
			return _mg.interligne;
		}
		
		public function set interligne(value:Number):void
		{
			_mg.siModif("interligne", value, actualiser);
		}
		
		/**
		 * Espacement entre caractères
		 */
		public function get ecartement():Number
		{
			return _mg.ecartement;
		}
		
		public function set ecartement(value:Number):void
		{
			_mg.siModif("ecartement", value, actualiser);
		}
		
		/**
		 * Format du texte
		 */
		public function get fmt():TextFormat
		{
			return _run.fmt;
		}
		
		public function set fmt(value:TextFormat):void
		{
			_run.fmt = value;
			actualiser();
		}
		
		/**
		 * Texte affiché
		 */
		public function get texte():String
		{
			return _run.texte;
		}
		
		public function set texte(value:String):void
		{
			_run.texte = value;
			actualiser();
		}
	}
}